#include "Cond.hpp"
#include "my_Lock.hpp"
#include "Log.hpp"
#include "Thread.hpp"

#include <iostream>
#include <pthread.h>
#include <vector>
#include <queue>
#include <memory>
#include<iterator>

using namespace LogMoudle;
using namespace ThreadMoudle;

// 在线程池中添加相应的单例模式

namespace ThreadPoolMoudle
{

    const static int DefaultNumber = 10;
    template <typename T>

    class ThreadPool
    {
    private:
        int _thread_number;
        std::vector<Thread<T>> _threads;
        std::queue<T> _task;

        Cond _condlock;
        Mutex _mutex;

        int wait_number;
        bool isruning;

        static ThreadPool<T> *instance;
	    static Mutex mutex; //只用来保护单例
       

    private:
    void Hander_task()//对当前的任务进行处理
    {
        //获取当前线程的名称
        // std::string name= GetThreadNameFromNptl(); 
        std::string name= std::string("thread-") += std::to_string(gettid()); 
        LOG(Logevel::INFO)<<name<<"is runing....";

        while(true)
        {
            LockGuard lock(_mutex);

            while(_task.empty()&&isruning)
            {
                wait_number++;
                _condlock.Wait(_mutex.GetMutex());
                wait_number--;
            }

            if(_task.empty()&&!isruning)
            {
                break;
            }

            T t=_task.front();
            _task.pop();
            LOG(Logevel::INFO)<<name<<"get a task";
            
        }
    }

    public:
       
        ThreadPool(int thread_number = DefaultNumber) : _thread_number(thread_number),
                                                        wait_number(0), isruning(false)
        {
           
            LOG(Logevel::INFO) << "threadpool creat";
        }

        void InintThreadPool()
        {
            for (int num = 0; num < _thread_number; num++)
            {
                _threads.emplace_back(std::bind(&ThreadPool::Hander_task,this));
                LOG(Logevel::INFO) << "init thread" << _threads.back().name();
            }
        }

        static ThreadPool<T>* GetInstance()
        {
            if(instance==nullptr)
            {
                 LockModule::LockGuard lockguard(mutex);
                 if(instance==nullptr)
                 {
                    instance=new ThreadPool<T>();
                    instance->InintThreadPool();
                    instance->Start();
                    LOG(Logevel::INFO)<<"创建单例线程池";
                    return instance;
                 }
            }
            LOG(Logevel::INFO)<<"获取线程池单例";
            return instance;  
        }

        void Start()
        {
            isruning = true;
            for (auto &a : this->_threads)
            {
                a.Start();
            }
            LOG(Logevel::INFO) << "thread start";
        }

        // 线程池退出
        void Stop()
        {
            _mutex.Lock();
            isruning = false;
            _condlock.NotifyAll();
            _mutex.UnLock();
            LOG(Logevel::INFO) << "线程池退出.....";
        }

        // 线程退出
        void Wait()
        {
            for (auto& a : this->_threads)
            {
                a.Join();
                LOG(Logevel::INFO) << a._name() << "退出....";
            }
        }

        bool Enqueue(const T &t)
        {
            bool ret = false;
            _mutex.Lock();
            if (isruning)
            {
                _task.push(t);
                if (wait_number > 0)
                {
                    _condlock.Notify();
                }
                LOG(Logevel::INFO) << "任务加入队列";
                ret = true;
            }
            _mutex.UnLock();

            return ret;
        }
    };

    template <typename T>
    ThreadPool<T> *ThreadPool<T>::instance = NULL;

    template <typename T>
    LockModule::Mutex ThreadPool<T>::mutex; //只用来保护单例

}